// requestAnimationFrame polyfill
;(function () {
    let lastTime = 0
    const vendors = ['webkit', 'moz']
    for (let x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']
        window.cancelAnimationFrame =
            window[vendors[x] + 'CancelAnimationFrame'] ||
            window[vendors[x] + 'CancelRequestAnimationFrame']
    }

    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function (callback) {
            let currTime = new Date().getTime()
            let timeToCall = Math.max(0, 16 - (currTime - lastTime))
            let id = window.setTimeout(function () {
                callback(currTime + timeToCall)
            }, timeToCall)
            lastTime = currTime + timeToCall
            return id
        }

    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function (id) {
            clearTimeout(id)
        }
})()

// To 动画类
class To {
    constructor(el, property, value, time, ease, onEnd, onChange) {
        this.el = el
        this.property = property
        this.value = value
        this.time = time
        this.ease = ease || ((a) => a)
        this.onEnd = onEnd
        this.onChange = onChange
        this.beginTime = new Date()
        this.tickID = null
        this.start()
    }

    start() {
        const el = this.el
        const property = this.property
        const dv = this.value - el[property]
        const time = this.time
        const ease = this.ease
        const onEnd = this.onEnd
        const onChange = this.onChange
        const beginTime = this.beginTime

        const toTick = () => {
            const dt = new Date() - beginTime
            if (dt >= time) {
                el[property] = this.value
                onChange && onChange(this.value)
                onEnd && onEnd(this.value)
                window.cancelAnimationFrame(this.tickID)
                this.tickID = null
            } else {
                el[property] = dv * ease(dt / time) + el[property]
                this.tickID = window.requestAnimationFrame(toTick)
                onChange && onChange(el[property])
            }
        }

        this.toTick = toTick
        this.toTick()
        To.List.push(this)
    }

    static stopAll() {
        for (let i = 0, len = To.List.length; i < len; i++) {
            window.cancelAnimationFrame(To.List[i].tickID)
        }
        To.List = []
    }

    static stop(to) {
        window.cancelAnimationFrame(to.tickID)
    }

    static get List() {
        return this._list || (this._list = [])
    }
}

// 导出 To 类及相关方法
export default To
export { To }
